home *** CD-ROM | disk | FTP | other *** search
-
- #
- # test for kjParseBuild module automatic parser generation
- #
- # lisp lists with strings, ints, vars, and setq
-
- import string
-
- ### The string representation for the grammar.
- ### Since this is used only by GrammarBuild()
- ### it could be put in a separate file with GrammarBuild()
- ### to save space/load time after Grammar compilation.
- ###
- GRAMMARSTRING ="""
- Value :: ## indicates Value is the root nonterminal for the grammar
- @R SetqRule :: Value >> ( setq var Value )
- @R ListRule :: Value >> ( ListTail
- @R TailFull :: ListTail >> Value ListTail
- @R TailEmpty :: ListTail >> )
- @R Varrule :: Value >> var
- @R Intrule :: Value >> int
- @R Strrule :: Value >> str
- """
-
- ### the name of the file in which to create the compiled
- ### grammar declarations
- COMPILEDFILENAME = "TESTLispG2.py"
-
- ### declare comment form(s) as regular expressions
- LISPCOMMENTREGEX = ";.*"
-
- ### declare regular expression string constants for terminals
-
- #integer terminal:::::::
- INTREGEX = "["+string.digits+"]+"
-
- #string terminal::::::::
- STRREGEX = '"[^\n"]*"'
-
- #var terminal::::::::
- VARREGEX = "["+string.letters+"]["+string.letters+string.digits+"]*"
-
- ### declare interpretation functions for terminals
-
- # int interpretation function: translates string to int:
- # Could use string.atoi without the extra level of indirection
- # but for demo purposes here it is.
- #
- def intInterp( str ):
- return string.atoi(str)
-
- # interpretation function for strings strips off the surrounding quotes.
- def stripQuotes( str ):
- if len(str)<2:
- TypeError, "string too short?"
- return str[1:len(str)-1]
-
- # interpretation function for vars just returns the recognized string
- def echo(string):
- return string
-
- # This function declares the nonterminals both in the
- # "grammar generation phase" and in loading the compiled
- # grammar after generation
- #
- def DeclareTerminals(Grammar):
- Grammar.Addterm("int", INTREGEX, intInterp)
- Grammar.Addterm("str", STRREGEX, stripQuotes)
- Grammar.Addterm("var", VARREGEX, echo)
-
- ### declare the rule reduction interpretation functions.
-
- # EchoValue() serves for Intrule and Strrule, since
- # we just want to echo the value returned by the
- # respective terminal interpretation functions.
- #
- # Parser delivers list of form [ interpreted_value ]
- def EchoValue( list, Context ):
- if len(list)!=1:
- raise TypeError, "this shouldn't happen! (1)"
- return list[0]
-
- # for Varrule interpreter must try to look up the value
- # in the Context dictionary
- #
- # Parser delivers list of form [ var_name ]
- def VarValue( list, Context ):
- if len(list)!=1:
- raise TypeError, "Huh? (2)"
- varName = list[0]
- if Context.has_key(varName):
- return Context[varName]
- else:
- raise NameError, "no such lisp variable in context "+varName
-
- # for an empty tail, return the empty list
- #
- # Parser delivers list of form [")"]
- def NilTail( list, Context ):
- if len(list) != 1 or list[0] != ")":
- return TypeError, "Bad reduction?"
- return []
-
- # For a full tail, add the new element to the front of the list
- #
- # Parser delivers list of form [Value, TailValue]
- def AddToList( list, Context ):
- if len(list) !=2:
- return TypeError, "Bad reduction?"
- return [ list[0] ] + list[1]
-
- # For a list, simply return the list determined by the tail
- #
- # Parser delivers list of form ["(", TailValue ]
- def MakeList( list, Context ):
- if len(list)!=2 or list[0]!="(":
- raise TypeError, "Bad reduction? (3)"
- return list[1]
-
- # For a setq, declare a new variable in the Context dictionary
- #
- # Parser delivers list of form # ["(", "setq", varName, Value, ")"]
- def DoSetq( list, Context):
- if len(list) != 5\
- or list[0] != "("\
- or list[1] != "setq"\
- or list[4] != ")":
- print list
- raise TypeError, "Bad reduction? (4)"
- VarName = list[2]
- if type(VarName) != type(''):
- raise TypeError, "Bad var name? (5)"
- Value = list[3]
- # add or set the variable in the Context dictionary
- Context[ VarName ] = Value
- return Value
-
- # This function Binds the named rules of the Grammar string to their
- # interpretation functions in a Grammar.
- #
- def BindRules(Grammar):
- Grammar.Bind( "Intrule", EchoValue )
- Grammar.Bind( "Strrule", EchoValue )
- Grammar.Bind( "Varrule", VarValue )
- Grammar.Bind( "TailEmpty", NilTail )
- Grammar.Bind( "TailFull", AddToList )
- Grammar.Bind( "ListRule", MakeList )
- Grammar.Bind( "SetqRule", DoSetq )
-
- # This function generates the grammar and dumps it to a file.
- # Since it will be used only once (after debugging),
- # it probably should be put in another file save memory/load-time.
- #
- # the result returned is a Grammar Object that can be used
- # for testing/debugging purposes.
- #
- # (maybe this should be made into a generic function?)
- def GrammarBuild():
- import kjParseBuild
-
- # initialize a Null compilable grammar to define
- LispG = kjParseBuild.NullCGrammar()
-
- # declare terminals for the grammar
- DeclareTerminals(LispG)
-
- # declare the keywords for the grammar
- # defun is not used, included here for demo purposes only
- LispG.Keywords("setq defun")
-
- # Declare punctuations
- # dot is not used here
- LispG.punct("().")
-
- # Declare Nonterms
- LispG.Nonterms("Value ListTail")
-
- # Declare comment forms
- LispG.comments([LISPCOMMENTREGEX])
-
- # Declare rules
- LispG.Declarerules(GRAMMARSTRING)
-
- # Compile the grammar
- LispG.Compile()
-
- # Write the grammar to a file except for
- # the function bindings (which must be rebound)
- outfile = open(COMPILEDFILENAME, "w")
- LispG.Reconstruct("LispG",outfile,"GRAMMAR")
- outfile.close()
-
- # for debugging purposes only, bind the rules
- # in the generated grammar
- BindRules(LispG)
-
- # return the generated Grammar
- return LispG
-
- # this function initializes the compiled grammar from
- # generated file.
- def LoadLispG():
- import TESTLispG2
- # make sure we have most recent version (during debugging)
- reload(TESTLispG2)
- # evaluate the grammar function from generated file
- LispG = TESTLispG2.GRAMMAR()
- # bind the semantics functions
- DeclareTerminals(LispG)
- BindRules(LispG)
- return LispG
-
- ########## test grammar generation
-
- # do generation
- Dummy = GrammarBuild()
-
- # load the grammar from the file as LispG
- LispG = LoadLispG()
-
- # declare an initial context, and do some tests.
- Context = { "x":3 }
- test1 = LispG.DoParse1( "()", Context)
- test2 = LispG.DoParse1( "(123)", Context)
- test3 = LispG.DoParse1( "(x)", Context)
- test4 = LispG.DoParse1( '" a string "', Context)
- test5 = LispG.DoParse1( "(setq y (1 2 3) )", Context )
- test6 = LispG.DoParse1( '(setq x ("a string" "another" 0))', Context )
- test7str = """
- ; this is a lisp comment
- (setq abc (("a" x)
- ("b" (setq d 12))
- ("c" y) ) ; another lisp comment
- )
- """
- test7 = LispG.DoParse1( test7str, Context)
-